#ifndef EXPRESSION_H
#define EXPRESSION_H
#include "interpreter.h"
class Expression {
public:
    /* local prototypes */
    enum OperatorOrder {
        kOrderNone,
        kOrderPrefix,
        kOrderInfix,
        kOrderPostfix
};

    /* a stack of expressions we use in evaluation */
    struct ExpressionStack {
        ExpressionStack *next;  /* the next lower item on the stack */
        Value *val;  /* the Value for this stack node */
        LexToken op;  /* the operator */
        unsigned short precedence;  /* the operator precedence of this node */
        unsigned char order;  /* the evaluation order of this operator */
    };

    /* operator precedence definitions */
    struct OpPrecedence {
        unsigned int prefixPrecedence : 4;
        unsigned int postfixPrecedence : 4;
        unsigned int infixPrecedence : 4;
        char *name;
    };

#ifdef DEBUG_EXPRESSIONS
    /* show the contents of the expression stack */
    static void ExpressionStackShow(Interpreter *pc, ExpressionStack *stackTop);
#endif

    static long ExpressionCoerceInteger(Value *val);

    static unsigned long ExpressionCoerceUnsignedInteger(Value *val);

    static double ExpressionCoerceFP(Value *val);

    /* assign any kind of Value */
    static void ExpressionAssign(Interpreter *pc, ParseState *parser, Value *destValue,
                          Value *sourceValue, int force, const char *funcName, int paramNo,
                          int allowPointerCoercion);

    /* do the '.' and '->' operators */
    static void ExpressionGetStructElement(Interpreter *pc, ParseState *parser,
                                    ExpressionStack **stackTop, LexToken token);

    /* parse an expression with operator precedence */
    static int ExpressionParse(Interpreter *pc, ParseState *parser, Value **result);

    /* parse an expression */
    static long ExpressionParseInt(Interpreter *pc, ParseState *parser);
private:
#ifdef DEBUG_EXPRESSIONS
	void ExpressionStackShow(Interpreter *pc, ExpressionStack *StackTop);
#endif
	static int IsTypeToken(ParseState *parser, LexToken t, Value *lexValue);
    /* assign an integer Value */
    static long ExpressionAssignInt(ParseState *parser, Value *DestValue, long FromInt, int After);
    /* assign a floating point Value */
    static double ExpressionAssignFP(ParseState *parser, Value *DestValue, double FromFP);
    /* push a node on to the expression stack */
    static void ExpressionStackPushValueNode(ParseState *parser, ExpressionStack **StackTop, Value *ValueLoc);
    /* push a blank Value on to the expression stack by type */
    static Value *ExpressionStackPushValueByType(ParseState *parser, ExpressionStack **StackTop, ValueType *PushType);
    /* push a Value on to the expression stack */
    static void ExpressionStackPushValue(ParseState *parser, ExpressionStack **StackTop, Value *PushValue);
	static void ExpressionStackPushLValue(Interpreter *pc, ParseState *parser, ExpressionStack **StackTop, Value *PushValue, int Offset);
	static void ExpressionStackPushDereference(Interpreter *pc, ParseState *parser, ExpressionStack **StackTop, Value *DereferenceValue);
	static void ExpressionPushInt(ParseState *parser, ExpressionStack **StackTop, long IntValue);
	static void ExpressionPushFP(ParseState *parser, ExpressionStack **StackTop, double FPValue);
    /* assign to a pointer */
    static void ExpressionAssignToPointer(ParseState *parser, Value *ToValue, Value *FromValue, const char *funcName, int ParamNo, int AllowPointerCoercion);
    /* evaluate the first half of a ternary operator x ? y : z */
    static void ExpressionQuestionMarkOperator(ParseState *parser, ExpressionStack **StackTop, Value *BottomValue, Value *TopValue);
    /* evaluate the second half of a ternary operator x ? y : z */
    static void ExpressionColonOperator(ParseState *parser, ExpressionStack **StackTop, Value *BottomValue, Value *TopValue);
    /* evaluate a prefix operator */
    static void ExpressionPrefixOperator(Interpreter *pc, ParseState *parser, ExpressionStack **StackTop, LexToken op, Value *TopValue);
    /* evaluate a postfix operator */
    static void ExpressionPostfixOperator(ParseState *parser, ExpressionStack **StackTop, LexToken op, Value *TopValue);
    /* evaluate an infix operator */
    static void ExpressionInfixOperator(Interpreter *pc, ParseState *parser, ExpressionStack **StackTop, LexToken op, Value *BottomValue, Value *TopValue);
    /* take the contents of the expression stack and compute the top until
    there's nothing greater than the given precedence */
    static void ExpressionStackCollapse(Interpreter *pc, ParseState *parser, ExpressionStack **StackTop, int precedence, int *IgnorePrecedence);
    /* push an operator on to the expression stack */
    static void ExpressionStackPushOperator(ParseState *parser, ExpressionStack **StackTop, OperatorOrder order, LexToken token, int precedence);
    /* do a parameterized macro call */
    static void ExpressionParseMacroCall(Interpreter *pc, ParseState *parser, ExpressionStack **StackTop, const char *MacroName, struct MacroDef *MDef);
    /* do a function call */
    static void ExpressionParseFunctionCall(Interpreter *pc, ParseState *parser, ExpressionStack **StackTop, const char *funcName, int RunIt);
    static const OpPrecedence operatorPrecedence[];
};
#endif //EXPRESSION_H